package com.wjf.birdfish.hibernate;

import org.hibernate.*;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;

import java.util.List;
import java.util.ArrayList;

public class PageCriteria implements Criteria {
    private Criteria local;
    private List<Order> orderList = new ArrayList<Order>();
    private List<PageCriteria> subcriteriaList = new ArrayList<PageCriteria>();

    public PageCriteria(Criteria criteria) {
        local = criteria;
    }

    public String getAlias() {
        return local.getAlias();
    }

    public Criteria setProjection(Projection projection) {
        local.setProjection(projection);
        return this;
    }

    public Criteria add(Criterion criterion) {
        local.add(criterion);
        return this;
    }

    public Criteria addOrder(Order order) {
        orderList.add(order);
        return this;
    }

    public void applyOrder() {
        for (Order order : orderList) {
            local.addOrder(order);
        }
        for (PageCriteria criteria : subcriteriaList) {
            criteria.applyOrder();
        }
    }

    public Criteria setFetchMode(String associationPath, FetchMode fetchMode) throws HibernateException {
        local.setFetchMode(associationPath, fetchMode);
        return this;
    }

    public Criteria setLockMode(LockMode lockMode) {
        local.setLockMode(lockMode);
        return this;
    }

    public Criteria setLockMode(String alias, LockMode lockMode) {
        local.setLockMode(alias, lockMode);
        return this;
    }

    public Criteria createAlias(String associationPath, String alias) throws HibernateException {
        local.createAlias(associationPath, alias);
        return this;
    }

    public Criteria createAlias(String associationPath, String alias, int joinType) throws HibernateException {
        local.createAlias(associationPath, alias, joinType);
        return this;
    }

    public Criteria createCriteria(String associationPath) throws HibernateException {
        return registerSubPageCriteria(new PageCriteria(local.createCriteria(associationPath)));
    }

    public Criteria createCriteria(String associationPath, int joinType) throws HibernateException {
        return registerSubPageCriteria(new PageCriteria(local.createCriteria(associationPath, joinType)));
    }

    public Criteria createCriteria(String associationPath, String alias) throws HibernateException {
        return registerSubPageCriteria(new PageCriteria(local.createCriteria(associationPath, alias)));
    }

    public Criteria createCriteria(String associationPath, String alias, int joinType)
            throws HibernateException {
        return registerSubPageCriteria(new PageCriteria(local.createAlias(associationPath, alias, joinType)));
    }

    private Criteria registerSubPageCriteria(PageCriteria pageCriteria) {
        subcriteriaList.add(pageCriteria);
        return pageCriteria;
    }

    public Criteria setResultTransformer(ResultTransformer resultTransformer) {
        local.setResultTransformer(resultTransformer);
        return this;
    }

    public Criteria setMaxResults(int maxResults) {
        local.setMaxResults(maxResults);
        return this;
    }

    public Criteria setFirstResult(int firstResult) {
        local.setFirstResult(firstResult);
        return this;
    }

    public Criteria setFetchSize(int fetchSize) {
        local.setFetchSize(fetchSize);
        return this;
    }

    public Criteria setTimeout(int timeout) {
        local.setTimeout(timeout);
        return this;
    }

    public Criteria setCacheable(boolean cacheable) {
        local.setCacheable(cacheable);
        return this;
    }

    public Criteria setCacheRegion(String cacheRegion) {
        local.setCacheRegion(cacheRegion);
        return this;
    }

    public Criteria setComment(String comment) {
        local.setComment(comment);
        return this;
    }

    public Criteria setFlushMode(FlushMode flushMode) {
        local.setFlushMode(flushMode);
        return this;
    }

    public Criteria setCacheMode(CacheMode cacheMode) {
        local.setCacheMode(cacheMode);
        return this;
    }

    @SuppressWarnings("rawtypes")
	public List list() throws HibernateException {
        return local.list();
    }

    public ScrollableResults scroll() throws HibernateException {
        return local.scroll();
    }

    public ScrollableResults scroll(ScrollMode scrollMode) throws HibernateException {
        return local.scroll(scrollMode);
    }

    public Object uniqueResult() throws HibernateException {
        return local.uniqueResult();
    }
}
